from rctk.layouts import TabbedLayout, GridLayout, StaticHBox
from rctk.widgets import Panel, StaticText, Text, Button, Dropdown, Window, List, Date
from rctk.widgets.grid import Grid, Column

from vcr.model import Customer, Project, Activity, Registration
from vcr import db

from datetime import date
import os

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, scoped_session

class ProjectAddDialog(Window):
    def __init__(self, parent, tk):
        super(ProjectAddDialog, self).__init__(tk, title="Add new project", modal=True)
        self.parent = parent

        self.setLayout(GridLayout(columns=2))
        self.append(StaticText(self.tk, "Project name"))
        self.projectname = Text(self.tk)
        self.projectname.change = lambda event: self.validate()
        self.append(self.projectname)
        self.append(StaticText(self.tk, "Customer"))
        self.customer = Dropdown(tk, db.customers(self.parent.orm))
        self.append(self.customer)

        panel = Panel(tk)
        panel.setLayout(StaticHBox(2))
        cancel = Button(self.tk, "Cancel")
        self.addbutton = Button(self.tk, "Add")
        panel.append(cancel)
        panel.append(self.addbutton)

        cancel.click = self.cancel
        self.addbutton.click = self.add
        self.addbutton.state = Button.DISABLED
        self.append(panel, row=2, col=1)

        self.layout()

    def validate(self):
        """ 
            verify a valid projectname has been entered and enable add button 
        """
        projectname = self.projectname.value.strip()
        if projectname:
            self.addbutton.state = Button.ENABLED
        else:
            self.addbutton.state = Button.DISABLED

    def add(self, event):
        ## validate: nonempty, not exists
        projectname = self.projectname.value.strip()
        customer = self.customer.value

        if projectname:
            p = Project(projectname)
            p.customer_id = int(customer)
            self.parent.orm.add(p)
            self.parent.orm.commit() ## required in current web setup?

            self.parent.project.add(p.id, p.name)
            self.parent.project.value = p.id
        self.close()

    def cancel(self, event):
        self.close()

def make_date(str):
    """ convert YYYY-MM-DD into a datetime.date """
    day,month,year = [int(x) for x in str.split("-")]
    pydate = date(day, month, year)
    return pydate

class VCRApp(object):
    def __init__(self):
        pass

    def projects(self):
        return [("", "-- select --"), ("new", "Add project...")] + \
               db.projects(self.orm)

    def activities(self):
        return db.activities(self.orm)

    def project_click(self, event):
        """
            A selection in the project dropdown has been made,
            see if we need to add new projects
        """
        selection = self.project.value
        if selection == "new":
            d = ProjectAddDialog(self, self.tk)

    def add_registration(self, event):
        p = self.project.value
        a = self.activity.value
        description = self.description.value

        dh, dm = (int(x) for x in self.duration.value.split(":"))
        d = dh*3600+dm
        date = self.date.value

        r = Registration(duration=d)
        r.project_id = int(p)
        r.activity_id = int(a)
        r.when = make_date(date)
        r.description = description

        self.orm.add(r)
        self.orm.commit()

        ## clear values, reset selections to default (or not?)

        self.registrations.add((r.project.name, r.activity.name, r.duration))

        ## update counters

        total = db.day_total(self.orm, r.when)
        self.daily.text = str(total)
        weektotal = db.week_total(self.orm, r.when)
        self.weekly.text = str(weektotal)

        ## clear entry
        self.project.reset()
        self.activity.reset()
        self.duration.value = ""
        self.description.value = ""

    def setup_registrations(self, panel, tk):
        panel.setLayout(GridLayout(rows=10, columns=2))

        self.date = Date(tk)
        self.date.value = date.today().strftime("%Y-%m-%d")
        self.date.change = self.date_changed
        panel.append(self.date, colspan=2)

        ## entry
        panel.append(StaticText(tk, "Project"))
        self.project = Dropdown(tk, self.projects())
        panel.append(self.project)

        self.project.click = self.project_click

        panel.append(StaticText(tk, "Activity"))
        self.activity = Dropdown(tk, self.activities())
        panel.append(self.activity)

        panel.append(StaticText(tk, "Duration (h:m)"))
        self.duration = Text(tk)
        self.duration.change = lambda event: self.validate()
        panel.append(self.duration)

        panel.append(StaticText(tk, "Description"), colspan=2)
        self.description = Text(tk, rows=4)
        panel.append(self.description, colspan=2)

        self.button = Button(tk, "Add")
        panel.append(self.button, colspan=2) # align=right
        self.button.click = self.add_registration
        self.button.state = Button.DISABLED
        ## also add project/activity to validation!


        ## listing
        self.registrations = Grid(tk, [ Column('Project'), Column('Activity'), Column('Duration', sorttype=Column.INT)])

        panel.append(self.registrations, expand_horizontal=True, colspan=2)

        today = date.today()

        ## totals. load_date will fill these in
        panel.append(StaticText(tk, "Daily total"))
        self.daily = StaticText(tk, "")
        panel.append(self.daily)

        panel.append(StaticText(tk, "Weekly total"))
        self.weekly = StaticText(tk, "")
        panel.append(self.weekly)

        self.load_date(today)

    def validate(self):
        """ validate input, if everything ok, enable "add" button """
        p = self.project.value
        a = self.activity.value
        d = self.duration.value

        if p in ("", "new"):
            self.button.state = Button.DISABLED
            return
        if d.count(":") != 1:
            self.button.state = Button.DISABLED
            return
        h, m = d.split(":")
        if not (h.isdigit() and m.isdigit()):
            self.button.state = Button.DISABLED
            return

        ## everything is ok!
        self.button.state = Button.ENABLED

    def load_date(self, date):
        """ load a specific date into the registration panel.
            This will clear all fields if necessary """
        self.registrations.clear()
        total = db.day_total(self.orm, date)
        self.daily.text = str(total)
        weektotal = db.week_total(self.orm, date)
        self.weekly.text = str(weektotal)

        for a in db.registrations(self.orm, date):
            self.registrations.add(a)

    def date_changed(self, event):
        """ the datefield has changed """
        self.load_date(make_date(self.date.value))

    def setup_reports(self, panel, tk):
        pass

    def run(self, tk):
        path = os.path.join(tk.startupdir, 'vcr.db')
        engine = create_engine("sqlite:///" + path, echo=True)
        self.orm = scoped_session(sessionmaker(bind=engine))
        self.tk = tk
        root = tk.root()
        ## set root size (explicitly)
        root.setLayout(TabbedLayout())
        registration_panel = Panel(tk)
        # reports_panel = Panel(tk)

        root.append(registration_panel, title="Registrations")
        # root.append(reports_panel, title="Reports")
        self.setup_registrations(registration_panel, tk)
        # self.setup_reports(reports_panel,tk)
        root.layout()

def main():
    """ for standalone running """
    from rctk.webpy import serve
    from rctk.sessions import Session, Manager
    import os

    manager = Manager(Session, VCRApp, os.getcwd())
    serve(manager)

